#region Microsoft Public License
/*
 * (c) Copyright Chenjun Wu. http://utablesdk.codeplex.com
 * 
 * This source is subject to the Microsoft Public License (Ms-PL).
 * Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
 * All other rights reserved.
 */
#endregion

﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using UTable.Logger;
using System.Reflection;
using System.Xml.Serialization;
using System.ComponentModel;

namespace UTable.Config
{
    [Serializable]
    public class InstanceConfig
    {
        private NLog.Logger logger = NLog.LogManager.GetLogger("UTable.Config.InstanceConfig");

        private Object _instance = null;

        public ClassConfig Class { get; set; }

        [XmlArray("Properties"), 
         XmlArrayItem("Property", typeof(PropertyConfig))]
        public List<PropertyConfig> Properties { get; set; }

        public Object GetInstace()
        {
            if (_instance == null)
            {
                // create the instance
                _instance = Class.CreateInstance();
                if (_instance != null && Properties != null)
                {
                    // inject the properties into the instance
                    foreach (PropertyConfig prop in Properties)
                    {
                        try
                        {
                            PropertyInfo propInfo = _instance.GetType().GetProperty(prop.Name);
                            if (propInfo == null)
                            {
                                logger.Error("Does not have property " + prop.Name + " in instance " + Class.ClassType);
                                continue;
                            }
                            if (!propInfo.CanWrite)
                            {
                                logger.Error("Cannot write to property " + prop.Name + " in instance " + Class.ClassType);
                                continue;
                            }
                            if (prop.Value != null)
                            {
                                object val = System.Convert.ChangeType(prop.Value, propInfo.PropertyType);
                                propInfo.SetValue(_instance, val, null);
                                continue;
                            }
                            if (prop.InstanceValue != null)
                            {
                                object instanceValue = prop.InstanceValue.GetInstace();
                                if (instanceValue != null)
                                    propInfo.SetValue(_instance, instanceValue, null);
                                continue;
                            }

                        }
                        catch (System.Exception e)
                        {
                            logger.Error("Cannot load property " + prop.Name + " in instance " + Class.ClassType);
                            logger.Error("   The error is: " + e.Message);
                        }
                    }
                }
            }
            return _instance;
        }
    }
}
